﻿package Gameplay.Water 
{	
	import com.junkbyte.console.Cc;
	import flash.filters.ColorMatrixFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import Shaders.ShaderManagerEvent;
	import Shaders.ShadersManager;
	import Shaders.UserShader;	
		
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.ShaderFilter;
	import flash.utils.getTimer;
	import flash.events.FullScreenEvent;
	
	public class WaterPlane extends Sprite 
	{
		private const COmitNormal:int = 1;
		private const COmitFullscreen:int = 2;
		
		private var FTilesX:int;
		private var FTilesY:int;
		private var FWidth:int;
		private var FHeight:int;
		private var FStatic:Bitmap;
		private var FStaticCanvas:BitmapData;		
		private var FReflections:BitmapData;	
		private var FShader:UserShader;
		private var FFilter:ShaderFilter;
		private var FTimer:Number;
		private var FTicks:int;
		private var FOmitFrames:int;		
		private var FBumpIntensity:int;		
		
		public function WaterPlane():void
		{
			WaterTiles.Count = 10;
			FTimer = new Number(4);
			FTicks = 0;
			FOmitFrames = COmitFullscreen;
			FBumpIntensity = 32;
			addEventListener(Event.ADDED_TO_STAGE, OnAddedToStage);			
		}
		
		private function OnAddedToStage(e:Event):void 
		{					
			ShadersManager.addEventListener(ShaderManagerEvent.COMPLETE, OnSahderLaoded);
			ShadersManager.Load('http://c4.site90.com/flash/water/new/Media/Shaders/Distortion.pbj');
			//ShadersManager.Load('http://localhost/Flash/UnitTests/WaterPlaneTest_Plane/Media/Shaders/Distortion.pbj');
			
			OnStageResize();
			
			stage.addEventListener(Event.RESIZE, OnStageResize);
			stage.addEventListener(FullScreenEvent.FULL_SCREEN, OnFullscreen);
			removeEventListener(Event.ADDED_TO_STAGE, OnAddedToStage);					
		}
		
		private function OnFullscreen(e:FullScreenEvent):void
		{
			e.fullScreen ? FOmitFrames = COmitFullscreen: FOmitFrames = COmitNormal;
			Cc.logch('Water', 'Omit every ' + FOmitFrames + ' frame');
		}
		
		private function OnSahderLaoded(e:ShaderManagerEvent):void 
		{			
			FShader = e.Data;			
			FFilter = new ShaderFilter(FShader);
			InitializeShader();
		}
		
		private function InitializeShader():void
		{
			if (FShader && FStatic)
			{				
				FTicks = 0;
				FShader.data.WaterSource.input = FStaticCanvas;				
				FShader.data.Intensity.value = [FBumpIntensity];
				FShader.data.MaxWidth.value = [FWidth + WaterTiles.TILE_WIDTH];
			}
		}
		
		private function OnEnterFarme(e:Event):void 
		{
			if (FShader)
			{
				FTicks++;
				FTimer += 0.025;			
				if (FTimer * FBumpIntensity >= FWidth + WaterTiles.TILE_WIDTH)
					FTimer = 0;								
				if (FTicks % FOmitFrames == 0)
				{
					FShader.data.Time.value = [(FTimer)];
					FStatic.bitmapData.applyFilter(FStaticCanvas, FStaticCanvas.rect, new Point(0, 0), FFilter);
				}
			}
		}
		
		private function OnStageResize(e:Event = null):void
		{
			FWidth = stage.stageWidth;
			FHeight = stage.stageHeight;
			FillTiles();			
		}
		
		private function FillTiles():void
		{
			removeEventListener(Event.ENTER_FRAME, OnEnterFarme);
			
			if (FStatic)
			{
				Cc.infoch('Water', 'Disposing bitmaps');				
				FStatic.bitmapData.dispose();
				removeChild(FStatic);
				FStatic = null;
				FStaticCanvas.dispose();				
				FStaticCanvas = null;				
			}
			
			var vTiles:Sprite = new Sprite();
			vTiles.graphics.beginFill(0x004488, 0);
			vTiles.graphics.drawRect(0, 0, FWidth, FHeight);
			vTiles.graphics.endFill();
			addChild(vTiles);
			
			FTilesX = Math.floor(width / WaterTiles.TILE_WIDTH) + 1;
			FTilesY = Math.floor(height / WaterTiles.TILE_HEIGHT) + 2;			
			width % WaterTiles.TILE_WIDTH > 0 ? FTilesX++ : FTilesX = FTilesX;
			height % WaterTiles.TILE_HEIGHT > 0 ? FTilesY++ : FTilesY = FTilesY;			
			var vXShift:int = 0;
			var vYShift:int = 0;
			var vTile:Bitmap;
			var vTileShift:Number = new Number();
			//var vFirstColumn:Vector.<Bitmap> = new Vector.<Bitmap>;
			
			for (var i:int = 0; i < FTilesX + 2; i++)
			{				
				for (var j:int = 0; j < FTilesY * 2; j++)
				{
					vTile = WaterTiles.RandomBitmap;										
					j % 2 > 0 ? vTileShift = WaterTiles.TILE_WIDTH / 2 : vTileShift = 0;
					vTile.x = WaterTiles.TILE_WIDTH * vXShift + vTileShift - WaterTiles.TILE_WIDTH;
					vTile.y = WaterTiles.TILE_HEIGHT / 2 * vYShift;					
					vYShift++;
					vTiles.addChild(vTile);
					//if (i == 2)
					//	vFirstColumn.push(vTile);				
				}
				vXShift++;
				vYShift = 0;
			}			
			
			var vMatrix:Matrix = new Matrix();
			vMatrix.tx = -WaterTiles.TILE_WIDTH;			
			FStaticCanvas = WaterBitmapData();						
			FStaticCanvas.draw(vTiles, vMatrix);		
			vMatrix = null;
			
			while (vTiles.numChildren > 0)
			{
				Bitmap(vTiles.getChildAt(0)).bitmapData.dispose();			
				vTiles.removeChildAt(0);
			}			
			vTiles.graphics.clear();
			removeChild(vTiles);			
			vTiles = null;
			
			FStatic = new Bitmap(new BitmapData(FWidth + WaterTiles.TILE_WIDTH, FHeight + WaterTiles.TILE_HEIGHT, true, 0xFF000000));
			FStatic.alpha = 0.5;
			FStatic.x -= WaterTiles.TILE_WIDTH;
			FStatic.y -= WaterTiles.TILE_HEIGHT;			
			addChild(FStatic);
			
			InitializeShader();
			
			addEventListener(Event.ENTER_FRAME, OnEnterFarme);
		}
		
		private function WaterBitmapData():BitmapData
		{
			return new BitmapData(FTilesX * WaterTiles.TILE_WIDTH, FTilesY * WaterTiles.TILE_HEIGHT, true, 0x00000000);
		}
		
		public function OmitFrames(AOmit:int):void
		{
			FOmitFrames = AOmit;			
		}
	}
}